package com.rapida.bitmap;

import java.io.File;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.ImageView;

import com.rapida.file.FileManager;
import com.rapida.net.HTTPClient;

public class NetBitmapManager {
	private static final String TAG = "NetBitmapManager";
	private static HashMap<String, SoftReference<Bitmap>> mCache;
	private static ExecutorService mPool;
	private static Map<ImageView, String> mImageViews;
    private static NetBitmapManager mInst;
    private Context mContext;
	static {
		mCache = new HashMap<String, SoftReference<Bitmap>>();
		mPool = Executors.newFixedThreadPool(20);
		mImageViews = Collections.synchronizedMap(new WeakHashMap<ImageView, String>());
	}

    public static NetBitmapManager get(Context context) {
        if (mInst == null) {
            mInst = new NetBitmapManager(context);
        }
        return mInst;
    }

    private NetBitmapManager(Context context) {
        mContext = context;
    }

	public void loadBitmap(String url, Bitmap defaultBmp, ImageView imageView) {
		loadBitmap(url, imageView, defaultBmp, 0, 0);
	}

    public void loadBitmap(String url, int id, ImageView imageView) {
        Bitmap defaultBmp = BitmapFactory.decodeResource(mContext.getResources(), id);
        loadBitmap(url, imageView, defaultBmp, 0, 0);
    }

    public void loadBitmap(String url, ImageView imageView) {
        loadBitmap(url, imageView, null, 0, 0);
    }

	private void loadBitmap(String url, ImageView imageView, Bitmap defaultBmp, int width, int height) {
		mImageViews.put(imageView, url);
		Bitmap bitmap = getBitmapFromCache(url);

		if (bitmap != null) {
			imageView.setImageBitmap(bitmap);
		} else {
			String filename = getFileName(url);
			String filepath = imageView.getContext().getFilesDir() + File.separator + filename;
			File file = new File(filepath);
			if (file.exists()) {
				Bitmap bmp = ImageManager.getBitmap(imageView.getContext(), filename);
				imageView.setImageBitmap(bmp);
			} else {
				imageView.setImageBitmap(defaultBmp);
				addJob(url, imageView, width, height);
			}
		}
	}

	private void addJob(final String url, final ImageView imageView, final int width,
			final int height) {
		final Handler handler = new Handler() {
			public void handleMessage(Message msg) {
				String tag = mImageViews.get(imageView);
				if (tag != null && tag.equals(url)) {
					if (msg.obj != null) {
						imageView.setImageBitmap((Bitmap) msg.obj);
						try {
							FileManager.saveImage(imageView.getContext(), getFileName(url),
									(Bitmap) msg.obj);
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
				}
			}
		};

		mPool.execute(new Runnable() {
			public void run() {
				Message message = Message.obtain();
				message.obj = downloadBitmap(url, width, height);
				handler.sendMessage(message);
			}
		});
	}

	private String getFileName(String url) {
		if (url == null) {
			return "";
		}
		return url.substring(url.lastIndexOf(File.separator) + 1);
	}

	public Bitmap getBitmapFromCache(String url) {
		Bitmap bitmap = null;
		if (mCache.containsKey(url)) {
			bitmap = mCache.get(url).get();
		}
		return bitmap;
	}

	private Bitmap downloadBitmap(String url, int width, int height) {
		Bitmap bitmap = null;
		try {
			HTTPClient clinet = HTTPClient.getHTTPClient();
			bitmap = clinet.requestUrl(HTTPClient.GET_METHOD, url).getBitmap();
			if (width > 0 && height > 0) {
				bitmap = Bitmap.createScaledBitmap(bitmap, width, height, true);
			}
			mCache.put(url, new SoftReference<Bitmap>(bitmap));
		} catch (Exception e) {
			Log.d(TAG, "downloadBitmap() Exception");
		}
		return bitmap;
	}
}
